package com.hahaliu.hahaliu.controller.user;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.hahaliu.hahaliu.common.context.CurrentUser;
import com.hahaliu.hahaliu.common.exception.BaseException;
import com.hahaliu.hahaliu.common.result.Result;
import com.hahaliu.hahaliu.common.utils.RedisUtil;
import com.hahaliu.hahaliu.mapper.FavoriteVideoMapper;
import com.hahaliu.hahaliu.mapper.VideoMapper;
import com.hahaliu.hahaliu.pojo.entity.FavoriteVideo;
import com.hahaliu.hahaliu.pojo.entity.Video;
import com.hahaliu.hahaliu.pojo.vo.VideoInfoVO;
import com.hahaliu.hahaliu.service.user.UserService;
import com.hahaliu.hahaliu.service.video.VideoService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;
import java.util.stream.Collectors;

@RestController("userVideoController")
@RequestMapping("/user/video")
@Api(tags = "用户端视频相关接口")
@Slf4j
public class VideoController {
	@Autowired
	private VideoService videoService;

	@Autowired
	private UserService userService;

	@Autowired
	private FavoriteVideoMapper favoriteVideoMapper;

	@Autowired
	private VideoMapper videoMapper;

	@Autowired
	private CurrentUser currentUser;

	@Autowired
	private SqlSessionFactory sqlSessionFactory;

	@Autowired
	private RedisUtil redisUtil;

	// TODO 后续考虑加入redis
	@GetMapping("/list")
	@ApiOperation("获取随机视频列表")
    public Result<List<VideoInfoVO>> list() {

		List<VideoInfoVO> videoInfoVOS = videoService.listWithUser();

		return Result.success(videoInfoVOS);
    }

	@GetMapping("/visitor")
	@ApiOperation("获取游客推荐")
	public Result<List<Map<String, Object>>> getVisitorList() {
		int count = 11;
		Set<Object> idSet = redisUtil.srandmember("video_status:1", count);
		List<Map<String, Object>> videoList = videoService.getVideosWithDataByIds(idSet, 1, count);
		// 随机打乱列表顺序
		Collections.shuffle(videoList);

		return Result.success(videoList);
	}

	/**
	 * 累加获取更多视频
	 * @param vids  曾经查询过的视频id列表，用于去重
	 * @return  每次返回新的10条视频，以及其id列表，并标注是否还有更多视频可以获取
	 */
	@GetMapping("/visitor/cumulative")
	public Result cumulativeVideosForVisitor(@RequestParam("vids") String vids) {
		Map<String, Object> map = new HashMap<>();
		List<Integer> vidsList = new ArrayList<>();
		if (!vids.trim().isEmpty()) {
			vidsList = Arrays.stream(vids.split(","))
					.map(Integer::parseInt)
					.collect(Collectors.toList());  // 从字符串切分出id列表
		}
		Set<Object> set = redisUtil.getMembers("video_status:1");
		if (set == null) {
			map.put("videos", new ArrayList<>());
			map.put("vids", new ArrayList<>());
			map.put("more", false);
			return Result.success(map);
		}
		vidsList.forEach(set::remove);  // 去除已获取的元素
		Set<Object> idSet = new HashSet<>();    // 存放将要返回的id集合
		Random random = new Random();
		// 随机获取10个vid
		for (int i = 0; i < 10 && !set.isEmpty(); i++) {
			Object[] arr = set.toArray();
			int randomIndex = random.nextInt(set.size());
			idSet.add(arr[randomIndex]);
			set.remove(arr[randomIndex]);   // 查过的元素移除
		}
		List<Map<String, Object>> videoList = videoService.getVideosWithDataByIds(idSet, 1, 10);
		Collections.shuffle(videoList);     // 随机打乱列表顺序
		map.put("videos", videoList);
		map.put("vids", idSet);
		if (!set.isEmpty()) {
			map.put("more", true);
		} else {
			map.put("more", false);
		}
		return Result.success(map);
	}

//	@GetMapping("/cumulative")
//	@ApiOperation("获取累加更多视频")
//	public Result<CumulativeVideoVO> getCumulativeList() {
//
//		log.info("获取累加更多视频");
//
//		List<Integer> videoIds = videoService.getVIds();
//		List<Integer> existVideoIds = new ArrayList<>(); // 现有视频 ID 列表
//
//		// 从 Redis 中获取拼接的 ID 字符串
//		String videoIdsString = redisTemplate.opsForValue().get("visitor:videoIds");
//
//		// 将字符串转换为 List<Integer>
//		if (videoIdsString != null) {
//			existVideoIds = Arrays.stream(videoIdsString.split(","))
//					.map(Integer::valueOf)
//					.collect(Collectors.toList());
//		}
//
//		// 从 videoIds 中排除 existVideoIds
//		List<Integer> finalExistVideoIds = existVideoIds;
//		List<Integer> filteredVideoIds = videoIds.stream()
//				.filter(id -> !finalExistVideoIds.contains(id))
//				.collect(Collectors.toList());
//
//		// 如果没有可用的视频 ID
//		boolean hasMore = !filteredVideoIds.isEmpty();
//
//		// 随机选择十条 ID
//		List<Integer> randomVideoIds;
//		if (hasMore) {
//			Collections.shuffle(filteredVideoIds); // 打乱顺序
//			randomVideoIds = filteredVideoIds.stream()
//					.limit(10) // 选择前十个
//					.collect(Collectors.toList());
//		} else {
//			randomVideoIds = Collections.emptyList(); // 没有更多视频时返回空列表
//		}
//
//		// 将 existVideoIds 和随机选择的 ID 合并
//		List<Integer> combinedVideoIds = new ArrayList<>(existVideoIds);
//		combinedVideoIds.addAll(randomVideoIds);
//
//		// 将合并后的 ID 存入 Redis
//		String combinedIdsString = combinedVideoIds.stream()
//				.map(String::valueOf)
//				.collect(Collectors.joining(","));
//		redisTemplate.opsForValue().set("visitor:videoIds", combinedIdsString);
//
//		// 获取视频信息
//		List<VideoInfoVO> resultList = new ArrayList<>();
//		for (Integer randomVideoId : randomVideoIds) {
//			resultList.add(videoService.getInfo(randomVideoId));
//		}
//
//		CumulativeVideoVO cumulativeVideoVO =
//				CumulativeVideoVO.builder()
//						.videoInfoVO(resultList)
//						.hasMore(hasMore)
//						.build();
//
//		return Result.success(cumulativeVideoVO);
//	}

	@GetMapping("/{vId}")
	@ApiOperation("获取视频详情")
	public Result<VideoInfoVO> getInfo(@PathVariable("vId") int vId) {

//		System.out.println(vId);
		VideoInfoVO videoInfoVO = videoService.getInfo(vId);

		return Result.success(videoInfoVO);
	}

	/**
	 * 更新视频状态，包括过审、不通过、删除，其中审核相关需要管理员权限，删除可以是管理员或者投稿用户
	 * @param vid 视频ID
	 * @param status 要修改的状态，1通过 2不通过 3删除
	 * @return 无data返回 仅返回响应
	 */
	@PostMapping("/change/status")
	@ApiOperation("更新视频状态")
	public Result updateStatus(@RequestParam("vid") Integer vid, @RequestParam("status") Integer status) {
		videoService.updateVideoStatus(vid, status);
		return Result.success();
	}

	/**
	 * 获取单条视频的信息
	 * @param vid   视频vid
	 * @return  视频信息
	 */
	@GetMapping("/get-one")
	@ApiOperation("获取单条视频的信息")
	public Result<VideoInfoVO> getOneVideo(@RequestParam("vid") Integer vid) {
		VideoInfoVO videoWithData = videoService.getVideoWithDataById(vid);
		if (videoWithData == null) {
			throw new BaseException("特丽丽没找到这个视频QAQ");
		}
		Video video = videoWithData.getVideo();
		if (video.getStatus() != 1) {
			throw new BaseException("特丽丽没找到个视频QAQ");
		}
		return Result.success(videoWithData);
	}

	@GetMapping("/recommend")
	@ApiOperation("获取推荐视频")
	public Result<List<VideoInfoVO>> getRecommend() {

		List<VideoInfoVO> recommendList = videoService.getRecommend();

		return Result.success(recommendList);
	}

	@GetMapping("/works")
	@ApiOperation("获取用户投稿的视频")
	public Result<Map<String, Object>> getUserWorks(@RequestParam("uid") Integer uid,
												   @RequestParam("rule") Integer rule,
												   @RequestParam("page") Integer page,
												   @RequestParam("quantity") Integer quantity) {
		Map<String, Object> map = new HashMap<>();
		Set<Object> set = redisUtil.zReverange("user_video_upload:" + uid, 0, -1);
		if (set == null || set.isEmpty()) {
			map.put("count", 0);
			map.put("list", Collections.emptyList());
			return Result.success(map);
		}
		List<Integer> list = new ArrayList<>();
		set.forEach(vid -> {
			list.add((Integer) vid);
		});
		map.put("count", set.size());
		switch (rule) {
			case 1:
				map.put("list", videoService.getVideosWithDataByIdsOrderByDesc(list, "upload_date", page, quantity));
				break;
			case 2:
				map.put("list", videoService.getVideosWithDataByIdsOrderByDesc(list, "play", page, quantity));
				break;
			case 3:
				map.put("list", videoService.getVideosWithDataByIdsOrderByDesc(list, "good", page, quantity));
				break;
			default:
				map.put("list", videoService.getVideosWithDataByIdsOrderByDesc(list, "upload_date", page, quantity));
		}
		return Result.success(map);
	}

	@GetMapping("/user/works/count")
	@ApiOperation("获取用户投稿数量")
	public Result<Long> getUserWorksCount() {
		Integer currentId = currentUser.getUserId();
		Long worksCount = videoService.getWorksCount(currentId);
		return Result.success(worksCount);
	}


//	@GetMapping("/favorite")
//	@ApiOperation("获取用户收藏夹的视频")
//	public Result<IPage<VideoInfoVO>> getUserCollectVideos(@RequestParam("fid") Integer fid,
//	                                                       @RequestParam("rule") Integer rule,
//	                                                       @RequestParam("page") Integer page,
//	                                                       @RequestParam("quantity") Integer quantity) {
//
//		// 根据收藏夹ID获取所有的视频Id
//		List<Integer> videoIds = new ArrayList<>();
//		QueryWrapper<FavoriteVideo>  queryWrapper = new QueryWrapper<>();
//		queryWrapper.eq("f_id", fid);
//        List<FavoriteVideo> favoriteVideos = favoriteVideoMapper.selectList(queryWrapper);
//		for (FavoriteVideo favoriteVideo : favoriteVideos) {
//			videoIds.add(favoriteVideo.getVId());
//		}
//
//		IPage<VideoInfoVO> videoInfoVOList;
//		switch (rule) {
//			case 1:
//				videoInfoVOList = videoService.getVideosWithDataByIdsOrderByDesc(videoIds, "upload_date", page, quantity);
//				break;
//			case 2:
//				videoInfoVOList = videoService.getVideosWithDataByIdsOrderByDesc(videoIds, "play", page, quantity);
//				break;
//			case 3:
//				videoInfoVOList = videoService.getVideosWithDataByIdsOrderByDesc(videoIds, "good", page, quantity);
//				break;
//			default:
//				videoInfoVOList = videoService.getVideosWithDataByIdsOrderByDesc(videoIds, null, page, quantity);
//		}
//		return Result.success(videoInfoVOList);
//	}

	/**
	 * 获取某个收藏夹的视频
	 * @param fid   收藏夹ID
	 * @param rule  排序规则 1 最近收藏 2 最多播放 3 最新投稿
	 * @param page  分页  从1开始
	 * @param quantity  每页查询数量
	 * @return  视频信息列表
	 */
	@GetMapping("/favorite")
	@ApiOperation("获取用户收藏夹的视频")
	public Result<List<Map<String, Object>>> getUserCollectVideos(@RequestParam("fid") Integer fid,
														   @RequestParam("rule") Integer rule,
														   @RequestParam("page") Integer page,
														   @RequestParam("quantity") Integer quantity) {
		Set<Object> set;
		if (rule == 1) {
			set = redisUtil.zReverange("favorite_video:" + fid, (long) (page - 1) * quantity, (long) page * quantity);
		} else {
			set = redisUtil.zReverange("favorite_video:" + fid, 0, -1);
		}
		if (set == null || set.isEmpty()) {
			return Result.success(Collections.emptyList());
		}
		List<Integer> list = new ArrayList<>();
		set.forEach(vid -> {
			list.add((Integer) vid);
		});
		List<Map<String, Object>> result;
		switch (rule) {
			case 1:
				result = videoService.getVideosWithDataByIdsOrderByDesc(list, null, page, quantity);
				break;
			case 2:
				result = videoService.getVideosWithDataByIdsOrderByDesc(list, "play", page, quantity);
				break;
			case 3:
				result = videoService.getVideosWithDataByIdsOrderByDesc(list, "upload_date", page, quantity);
				break;
			default:
				result = videoService.getVideosWithDataByIdsOrderByDesc(list, null, page, quantity);
		}
		if (result.isEmpty()) {
			return Result.success(result);
		}
		try (SqlSession sqlSession = sqlSessionFactory.openSession(ExecutorType.BATCH)) {
			result.stream().parallel().forEach(map -> {
				Video video = (Video) map.get("video");
				QueryWrapper<FavoriteVideo> queryWrapper = new QueryWrapper<>();
				queryWrapper.eq("v_id", video.getVId()).eq("f_id", fid);
				map.put("info", favoriteVideoMapper.selectOne(queryWrapper));
			});
			sqlSession.commit();
		}
		return Result.success(result);
	}

	/**
	 * 获取用户最近点赞视频列表
	 * @param uid   用户uid
	 * @param offset    偏移量，即当前已查询到多少条视频
	 * @param quantity  查询数量
	 * @return  视频信息列表
	 */
	@GetMapping("/user-love")
	@ApiOperation("获取用户最近点赞视频列表")
	public Result<List<Map<String, Object>>> getUserLoveMovies(@RequestParam("uid") Integer uid,
											@RequestParam("offset") Integer offset,
											@RequestParam("quantity") Integer quantity) {
		System.out.println("Received params: uid=" + uid + ", offset=" + offset + ", quantity=" + quantity);
		Set<Object> set = redisUtil.zReverange("love_video:" + uid, (long) offset, (long) offset + quantity - 1);
		if (set == null || set.isEmpty()) {
			return Result.success(Collections.emptyList());
		}
		List<Integer> list = new ArrayList<>();
		set.forEach(vid -> {
			list.add((Integer) vid);
		});
		return Result.success(videoService.getVideosWithDataByIdsOrderByDesc(list, null, 1, list.size()));
	}

	/**
	 * 获取当前登录用户最近播放视频列表
	 * @param offset    偏移量，即当前已查询到多少条视频
	 * @param quantity  查询数量
	 * @return  视频信息列表
	 */
	@GetMapping("/user-play")
	@ApiOperation("获取当前登录用户最近播放视频列表")
	public Result<List<Map<String, Object>>> getUserPlayMovies(@RequestParam("offset") Integer offset,
											@RequestParam("quantity") Integer quantity) {
		Integer uid = currentUser.getUserId();
		Set<Object> set = redisUtil.zReverange("user_video_history:" + uid, (long) offset, (long) offset + quantity - 1);
		if (set == null || set.isEmpty()) {
			return Result.success(Collections.emptyList());
		}
		List<Integer> list = new ArrayList<>();
		set.forEach(vid -> {
			list.add((Integer) vid);
		});
		return Result.success(videoService.getVideosWithDataByIdsOrderByDesc(list, null, 1, list.size()));
	}

}
